package org.cybzacg.convert.converters.date;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * YearMonth转换器
 * 专门处理YearMonth类型的转换
 *
 * @author cybzacg.blog
 * @version 4.0
 * @since 3.0
 */
@Slf4j
@Converter(
    name = "YearMonthConverter",
    priority = ConversionPriority.MEDIUM_HIGH,
    description = "YearMonth类型转换器，处理各种类型到java.time.YearMonth的转换",
    enabled = true,
    version = "4.0",
    author = "cybzacg.blog",
    supportedTypes = {YearMonth.class},
    tags = {"yearmonth", "time", "conversion"}
)
public class YearMonthConverter extends AbstractDateTimeConverter<YearMonth> {

    public YearMonthConverter() {
        super(YearMonth.class, ConversionPriority.MEDIUM_HIGH);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.YEAR_MONTH;
    }

    @Override
    protected YearMonth parseFromString(String str, DateTimeFormatter formatter) throws DateTimeParseException {
        // 尝试年月格式 YYYY-MM
        try {
            if (str.matches("\\d{4}-\\d{1,2}")) {
                return YearMonth.parse(str);
            }
        } catch (DateTimeParseException e) {
            // 继续尝试其他格式
        }

        // 尝试数字格式 YYYYMM
        try {
            if (str.matches("\\d{6}")) {
                int year = Integer.parseInt(str.substring(0, 4));
                int month = Integer.parseInt(str.substring(4, 6));
                return YearMonth.of(year, month);
            }
        } catch (Exception e) {
            // 继续尝试其他格式
        }

        // 尝试解析为LocalDate然后提取年月
        try {
            LocalDate date = LocalDate.parse(str, formatter);
            return YearMonth.from(date);
        } catch (DateTimeParseException e) {
            // 尝试解析为LocalDateTime然后提取年月
            LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
            return YearMonth.from(dateTime);
        }
    }

    @Override
    protected YearMonth convertFromInstant(Instant instant, ConversionContext context) {
        return YearMonth.from(instant.atZone(DEFAULT_ZONE_ID).toLocalDate());
    }

    @Override
    protected YearMonth convertFromNumber(Number source, ConversionContext context) {
        long value = source.longValue();

        // 如果是6位数字，解释为YYYYMM
        if (value >= 100001L && value <= 999912L) {
            int year = (int) (value / 100);
            int month = (int) (value % 100);

            if (month < 1 || month > 12) {
                throw new org.cybzacg.convert.exception.ConversionException(
                    org.cybzacg.convert.enums.ConversionError.FORMAT_ERROR,
                    "无效的月份: " + month);
            }

            return YearMonth.of(year, month);
        }

        // 否则只取年份部分，月份设为1月
        int year = (int) value;
        if (year < Year.MIN_VALUE || year > Year.MAX_VALUE) {
            throw new org.cybzacg.convert.exception.ConversionException(
                org.cybzacg.convert.enums.ConversionError.NUMBER_OVERFLOW,
                "年份超出有效范围: " + year);
        }

        return YearMonth.of(year, 1);
    }

    @Override
    protected String[] getSupportedPatterns() {
        // 合并日期和日期时间格式
        String[] datePatterns = org.cybzacg.convert.constants.DateFormats.DATE_FORMAT_PATTERNS;
        String[] datetimePatterns = org.cybzacg.convert.constants.DateFormats.DATETIME_FORMAT_PATTERNS;
        
        String[] allPatterns = new String[datePatterns.length + datetimePatterns.length];
        System.arraycopy(datePatterns, 0, allPatterns, 0, datePatterns.length);
        System.arraycopy(datetimePatterns, 0, allPatterns, datePatterns.length, datetimePatterns.length);
        
        return allPatterns;
    }

    @Override
    protected YearMonth convertFromOtherDateTime(Object source, ConversionContext context) {
        // LocalDateTime转换
        if (source instanceof LocalDateTime localDateTime) {
            return YearMonth.from(localDateTime);
        }

        // ZonedDateTime转换
        if (source instanceof ZonedDateTime zonedDateTime) {
            return YearMonth.from(zonedDateTime);
        }

        // LocalDate转换
        if (source instanceof LocalDate localDate) {
            return YearMonth.from(localDate);
        }

        // Year转换
        if (source instanceof Year year) {
            return year.atMonth(1);
        }

        return null;
    }

    @Override
    protected YearMonth getDefaultValue() {
        return org.cybzacg.convert.constants.DateTimeDefaults.YEAR_MONTH_DEFAULT;
    }
}
